using System;
using System.Collections.Generic;
using FishFillets.Data.Helpers;
using FishFillets.Model;
using FishFillets.Model.GameItems;

namespace FishFillets.Data.levels
{
    public abstract class BaseLevelScript
    {   
        private readonly ILevelAgent agent;
        protected BaseLevelScript(ILevelAgent agent)
        {
            this.agent = agent;
        }

        /// <summary>
        /// Method used for loading the initial Level model.
        /// </summary>
        /// <returns></returns>
        public abstract Level models();

        /// <summary>
        /// Method used for defining actions and scripting.
        /// </summary>
        public abstract void prog_init();

        /// <summary>
        /// Table with update scripts.
        /// </summary>
        protected List<Action> update_table;

        // room local variabless
        public int pokus;

        public Fish big;
        public Fish small;

        public const int dir_left = 0;
        public const int dir_right = 1;

        // -----------------------------------------------------------------
        // Update
        // -----------------------------------------------------------------    
    
        public void prog_update()
        {
            foreach (Action action in update_table)
            {
                action();
            }
        }

        #region ----- Original LUA mapped functions and procedures -------

        // procedures

        protected void sound_playMusic(string song)
        {
            agent.PlayMusic(song);
        }

        // -----------------------------------------------------------------
        // Compatibility functions
        // -----------------------------------------------------------------

        public bool no_dialog()
        {
            // TODO !
            return agent.no_dialog();
            // return !dialog_isDialog() && !game_isPlanning();
        }

        public bool isReady(Fish model)
        {
            return model.isAlive() && !model.isOut();
        }

        public bool odd(int number)
        {
            return math.mod(number, 2) == 1;
        }

        public int getRestartCount()
        {
            return agent.getRestartCount();
        }

        // -----------------------------------------------------------------
        // Planning
        // -----------------------------------------------------------------

        public void addm(int time, string text)
        {
            small.planDialog(time, text);
        }

        public void addv(int time, string text)
        {
            big.planDialog(time, text);
        }

        public void adddel(int time)
        {
            // TODO !
            //planTimeAction(time, () => {});
        }

        //public void planSet(model, variable_name, value)
        //{
        //}

        //public void planDialogSet(time, text, value, model, variable_name)
        //{
        //}

        public void planBusy(BaseItem model, bool busy)
        {
            planBusy(model, busy, 0);
        }

        public void planBusy(BaseItem model, bool busy, int delay)
        {
            // TODO !
            //planTimeAction(delay, () => { model.setBusy(busy); });
        }

        // -----------------------------------------------------------------
        // Distance measuring
        // -----------------------------------------------------------------

        // functions
        
        private static readonly Random r = new Random();
        public int random(int i)
        {
            return r.Next(i);
        }

        public int game_getCycles()
        {
            // TODO !
            return 10;
        }

        #endregion

        #region ----- internal new methods -------------------------------

        protected static bool[,] LoadMap(string[] p)
        {
            bool[,] map = new bool[p[0].Length,p.Length];
            for (int y = 0; y < p.Length; y++)
            {
                for (int x = 0; x < p[0].Length; x++)
                {
                    map[x, y] = p[y][x] == 'X';
                }
            }
            return map;
        }

        #endregion
    }

    public class math
    {
        public static int mod(int num1, int num2)
        {
            return num1 % num2;
        }
    }
}
